package com.atguigu.juc.day01.synch;

import java.util.concurrent.TimeUnit;

public class Demo02SyncMethod {

    // 场景一：创建一个对象，分别调用两个非静态同步方法
    // 运行效果：两个同步方法用的是同一把锁，所以发短信之后才能打电话
    public static void situation01(String[] args) {
        Phone phone = new Phone();
        new Thread(()->{
            phone.sendShortMessage();
        }, "thread-a").start();

        new Thread(()->{
            phone.call();
        }, "thread-b").start();

    }

    // 场景二：创建两个对象，分别调用两个非静态同步方法
    // 运行效果：两个同步方法用的不是同一把锁，不需要互相等待，所以发短信和打电话并行执行
    public static void situation02(String[] args) {
        Phone phone01 = new Phone();
        Phone phone02 = new Phone();
        new Thread(()->{
            phone01.sendShortMessage();
        }, "thread-a").start();

        new Thread(()->{
            phone02.call();
        }, "thread-b").start();

    }

    // 场景三：通过类名分别调用两个静态同步方法
    // 运行效果：使用同一个锁对象，互斥，需要等待
    public static void situation03(String[] args) {
        new Thread(()->{
            Phone.sendShortMessageStatic();
        }, "thread-a").start();

        new Thread(()->{
            Phone.callStatic();
        }, "thread-b").start();
    }

    // 场景四：通过类名调用静态同步方法发短信，通过对象调用非静态同步方法打电话
    // 运行效果：不是同一个锁对象，不互斥，不需要等待
    public static void main(String[] args) {
        new Thread(()->{
            Phone.sendShortMessageStatic();
        }, "thread-a").start();

        Phone phone = new Phone();
        new Thread(()->{
            phone.call();
        }, "thread-b").start();
    }

}

class Phone {

    // 非静态同步方法：锁对象是 this
    public synchronized void sendShortMessage() {
        try {
            System.out.println(Thread.currentThread().getName() + " 开始发短信。");

            TimeUnit.SECONDS.sleep(8);

            System.out.println(Thread.currentThread().getName() + " 完成发短信。");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    // 非静态同步方法：锁对象是 this
    public synchronized void call() {
        System.out.println(Thread.currentThread().getName() + " 开始打电话。");
        System.out.println(Thread.currentThread().getName() + " 完成打电话。");
    }

    // 静态同步方法：锁对象是 Phone.class
    public static synchronized void sendShortMessageStatic() {
        try {
            System.out.println(Thread.currentThread().getName() + " 开始发短信。");

            TimeUnit.SECONDS.sleep(8);

            System.out.println(Thread.currentThread().getName() + " 完成发短信。");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    // 静态同步方法：锁对象是 Phone.class
    public static synchronized void callStatic() {
        System.out.println(Thread.currentThread().getName() + " 开始打电话。");
        System.out.println(Thread.currentThread().getName() + " 完成打电话。");
    }

}